import test from '/@/utils/test';
let timer: any, flag: any, timeout: any;
import request from '/@/utils/request';
import { ElMessage } from 'element-plus';
const toolsMethods = <any>{
	uuid(len = 32, firstU = true, radix?: any) {
		let chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
		let uuid = [];
		radix = radix || chars.length;
		if (len) {
			// 如果指定uuid长度,只是取随机的字符,0|x为位运算,能去掉x的小数位,返回整数位
			for (let i = 0; i < len; i++) uuid[i] = chars[0 | (Math.random() * radix)];
		} else {
			let r;
			// rfc4122标准要求返回的uuid中,某些位为固定的字符
			uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
			uuid[14] = '4';
			for (let i = 0; i < 36; i++) {
				if (!uuid[i]) {
					r = 0 | (Math.random() * 16);
					uuid[i] = chars[i == 19 ? (r & 0x3) | 0x8 : r];
				}
			}
		}
		// 移除第一个字符,并用u替代,因为第一个字符为数值时,该guuid不能用作id或者class
		if (firstU) {
			uuid.shift();
			return 'u' + uuid.join('');
		} else {
			return uuid.join('');
		}
	},
	/**
	 * @description 深度克隆
	 * @param {object} obj 需要深度克隆的对象
	 * @param cache 缓存
	 * @returns {*} 克隆后的对象或者原值（不是对象）
	 */
	deepCopy(obj: object, cache = new WeakMap()) {
		if (obj === null || typeof obj !== 'object') return obj;
		if (cache.has(obj)) return cache.get(obj);
		let clone;
		if (obj instanceof Date) {
			clone = new Date(obj.getTime());
		} else if (obj instanceof RegExp) {
			clone = new RegExp(obj);
		} else if (obj instanceof Map) {
			clone = new Map(Array.from(obj, ([key, value]) => [key, toolsMethods.deepCopy(value, cache)]));
		} else if (obj instanceof Set) {
			clone = new Set(Array.from(obj, (value) => toolsMethods.deepCopy(value, cache)));
		} else if (Array.isArray(obj)) {
			clone = obj.map((value) => toolsMethods.deepCopy(value, cache));
		} else if (Object.prototype.toString.call(obj) === '[object Object]') {
			clone = Object.create(Object.getPrototypeOf(obj));
			cache.set(obj, clone);
			for (const [key, value] of Object.entries(obj)) {
				clone[key] = toolsMethods.deepCopy(value, cache);
			}
		} else {
			clone = Object.assign({}, obj);
		}
		return clone;
	},
	/**
	 * @description JS对象深度合并
	 * @param {object} target 需要拷贝的对象
	 * @param {object} source 拷贝的来源对象
	 * @returns {object|boolean} 深度合并后的对象或者false（入参有不是对象）
	 */
	deepMerge(target: any, source: any) {
		target = toolsMethods.deepCopy(target);
		if (typeof target !== 'object' || typeof source !== 'object') return false;
		for (const prop in source) {
			if (!source.hasOwnProperty(prop)) continue;
			if (prop in target) {
				if (typeof target[prop] !== 'object') {
					target[prop] = source[prop];
				} else if (typeof source[prop] !== 'object') {
					target[prop] = source[prop];
				} else if (target[prop].concat && source[prop].concat) {
					target[prop] = target[prop].concat(source[prop]);
				} else {
					target[prop] = toolsMethods.deepMerge(target[prop], source[prop]);
				}
			} else {
				target[prop] = source[prop];
			}
		}
		return target;
	},

	/**
	 * @description 打乱数组
	 * @param {array} array 需要打乱的数组
	 * @returns {array} 打乱后的数组
	 */
	randomArray(array: []) {
		// 原理是sort排序,Math.random()产生0<= x < 1之间的数,会导致x-0.05大于或者小于0
		return array.sort(() => Math.random() - 0.5);
	},
	deleteParams(row: any, rule: any) {
		let paramsKeys = Object.keys(row);
		let paramsValues = Object.values(row);
		let params = toolsMethods.deepCopy(row);
		paramsValues.forEach((item, index) => {
			if ((item === null || item === '' || item === undefined) && rule.indexOf(paramsKeys[index]) === -1) {
				delete params[paramsKeys[index]];
			}
		});
		return params;
	},
	/**
	 * 校验函数
	 * @param {Object} ruleForm 需要校验的对象
	 * @param {Array} rules 校验的规则数组
	 * @param {RegExp} pattern 要求此参数值为一个正则表达式，如： /\d+/，不能带引号，如："/\d+/"，组件会对字段进行正则判断，返回结果。
	 * @param {Number} min 最小值，如果字段类型为字符串和数组，会取字符串长度与数组长度(length)与min比较，如果字段是数值，则直接与min比较。
	 * @param {Number} max 最大值，规则同min参数
	 * @param {Number} len 指定长度，规则同min，优先级高于min和max
	 * @param {String} keys {Array} 指定的值，使用 场景 当数组为对象数组时 需要传入对象的规则校验 当keys为空时 仅判断array数组长度
	 * @param {String} father 父类 用户校验当前参数是否和父类一致
	 * @return null
	 */
	ruleParams(ruleForm: object, rules: any) {
		let flag = true;
		return new Promise((resolve: any, reject: any) => {
			//对数据进行校验
			// let keys = Object.keys(ruleForm);
			// let values = Object.values(ruleForm);
			if (rules && rules.length > 0) {
				for (let i = 0; i < rules.length; i++) {
					if (!toolsMethods.validation(rules[i], ruleForm)) {
						// toolsMethods.showTips(rules[i].msg || '请先补全信息');
						ElMessage.warning(rules[i].msg || '请先补全信息');
						flag = false;
						break;
					}
				}
				if (flag) resolve(toolsMethods.deepCopy(ruleForm));
				else reject(flag);
			} else {
				resolve();
			}
		});
	},
	/**
	 * 校验数据合法性
	 * @param {Object} rule 规则
	 * @param {any} params 数据
	 * @return null
	 */
	// string：必须是 string 类型，默认类型
	// number：必须是 number 类型
	// boolean：必须是 boolean 类型
	// method：必须是 function 类型
	// regexp：必须是 regexp 类型，这里的正则，指的是判断字段的内容是否一个正则表达式，而不是用这个正则去匹配字段值
	// integer：必须是整数类型
	// float：必须是浮点数类型
	// array：必须是 array 类型
	// object：必须是 object 类型
	// enum：必须出现在 enmu 指定的值中
	// date：必须是 date 类型
	// url：必须是 url 类型
	// hex：必须是 16 进制类型
	// email：必须是 email 类型
	// any：任意类型
	validation(rule: any, params: any) {
		switch (rule.type) {
			case 'string':
				return toolsMethods.patternTest(rule, params) && toolsMethods.commonTest(rule, params);
				break;
			case 'number':
				return toolsMethods.patternTest(rule, params) && toolsMethods.numberTest(rule, params);
				break;
			case 'array':
				return toolsMethods.arrayTest(rule, params);
				break;
		}
	},
	//基础校验
	commonTest(rule: any, params: any) {
		let commonResult = [];
		if (params[rule.prop]) commonResult.push(true);
		if (rule.len) commonResult.push(params[rule.prop].length === rule.len);
		if (rule.min) commonResult.push(params[rule.prop].length >= rule.min);
		if (rule.max) commonResult.push(params[rule.prop].length <= rule.max);
		if (rule.father) commonResult.push(params[rule.father] === params[rule.prop]);
		return commonResult && commonResult.length > 0 ? !commonResult.includes(false) : false;
	},
	//正则校验
	patternTest(rule: any, params: any) {
		if (!rule.pattern) return true;
		return new RegExp(rule.pattern).test(params[rule.prop]);
	},
	//数字校验
	numberTest(rule: any, params: any) {
		let commonResult = [];
		if (params[rule.prop]) commonResult.push(true);
		if (rule.min) commonResult.push(params[rule.prop] >= rule.min);
		if (rule.max) commonResult.push(params[rule.prop] <= rule.max);
		if (rule.father) commonResult.push(params[rule.father] === params[rule.prop]);
		return commonResult && commonResult.length > 0 ? !commonResult.includes(false) : false;
	},
	//数组校验
	arrayTest(rule: any, params: any) {
		if (rule.keys) {
			return params[rule.prop] && params[rule.prop].length > 0;
		} else {
			return params[rule.prop] && params[rule.prop].length > 0;
		}
	},
	//初始化对象赋值
	initRow(row: object, params: any) {
		if (params) {
			let rowKeys = Object.keys(row);
			let paramsKeys = Object.keys(params);
			let data = <any>{};
			rowKeys.forEach((item) => {
				if (paramsKeys.indexOf(item) > -1) {
					data[item] = params[item];
				}
			});
			return data;
		} else {
			return row;
		}
	},
	//对象里面是数组的转字符串拼接
	arrayToString(row: any, split = ',') {
		let paramsKeys = Object.keys(row);
		let paramsValues = Object.values(row);
		let params = toolsMethods.deepCopy(row);
		paramsValues.forEach((item, index) => {
			if (Array.isArray(item)) {
				params[paramsKeys[index]] = item.join(split);
			}
		});
		return params;
	},
	//对象里面符合条件的转为数组
	stringToArray(row: any, rule: any, split = ',') {
		let paramsKeys = Object.keys(row);
		let params = toolsMethods.deepCopy(row);
		paramsKeys.forEach((item: string, index: number) => {
			if (rule.indexOf(item) > -1) {
				params[paramsKeys[index]] = params[paramsKeys[index]] ? params[paramsKeys[index]].split(split) : [];
			}
		});
		return params;
	},
	//过滤两个数组内容
	arrayfilter(arr1: [], arr2: [], flag = 1) {
		// flag  1两个数组不同的内容 2 两个数组相同的内容
		if (flag === 1) {
			return [...new Set(arr1.map((item) => JSON.stringify(item)))]
				.filter((x) => !new Set(arr2.map((item) => JSON.stringify(item))).has(x))
				.map((item) => JSON.parse(item));
		} else {
			return [...new Set(arr1.map((item) => JSON.stringify(item)))]
				.filter((x) => new Set(arr2.map((item) => JSON.stringify(item))).has(x))
				.map((item) => JSON.parse(item));
		}
	},
	/**
	 * 防抖原理：一定时间内，只有最后一次操作，再过wait毫秒后才执行函数
	 *
	 * @param {Function} func 要执行的回调函数
	 * @param {Number} wait 延时的时间
	 * @param {Boolean} immediate 是否立即执行
	 * @return null
	 */

	debounce(func: Function, wait = 500, immediate = false) {
		// 清除定时器
		if (timeout !== null) clearTimeout(timeout);
		// 立即执行，此类情况一般用不到
		if (immediate) {
			const callNow = !timeout;
			timeout = setTimeout(() => {
				timeout = null;
			}, wait);
			if (callNow) typeof func === 'function' && func();
		} else {
			// 设置定时器，当最后一次操作后，timeout不会再被清除，所以在延时wait毫秒后执行func回调方法
			timeout = setTimeout(() => {
				typeof func === 'function' && func();
			}, wait);
		}
	},
	/**
	 * 节流原理：在一定时间内，只能触发一次
	 *
	 * @param {Function} func 要执行的回调函数
	 * @param {Number} wait 延时的时间
	 * @param {Boolean} immediate 是否立即执行
	 * @return null
	 */
	throttle(func: Function, wait = 500, immediate = true) {
		if (immediate) {
			if (!flag) {
				flag = true;
				// 如果是立即执行，则在wait毫秒内开始时执行
				typeof func === 'function' && func();
				timer = setTimeout(() => {
					flag = false;
				}, wait);
			}
		} else if (!flag) {
			flag = true;
			// 如果是非立即执行，则在wait毫秒内的结束处执行
			timer = setTimeout(() => {
				flag = false;
				typeof func === 'function' && func();
			}, wait);
		}
	},
	async requestApi(event: requestApi) {
		await toolsMethods.ruleParams(event.data, event.rules);
		// if (event.method === 'body') event.headers = { ...event.headers, 'Content-Type': 'application/json' };
		return request(event);
	},
};

export default { ...toolsMethods };
